﻿using Avalon.Core.MVC.Actions;
using Avalon.Core.MVC.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Routing;

namespace Avalon.Core.Providers {
    public class PipelineProvider : BaseProvider, IPipelineProvider {
        private static List<PipelineDescriptor> _pipelines { get; set; }

        /// <summary>
        /// Empty CTOR, this constructor assumes that the current RequestContext is already set in the ContextProvider. 
        /// If not, this will throw an exception.
        /// </summary>
        public PipelineProvider() {
            if (_pipelines == null) initializePipelines();
        }

        /// <summary>
        /// Get the pipeline descriptor
        /// </summary>
        /// <param name="pipelineType"></param>
        /// <returns></returns>
        public PipelineDescriptor GetPipelineDescriptor(PipelineType pipelineType) {
            IRendererProvider rendererProvider = ProviderContainer.Current.RendererProvider;
            IRendererDescriptor rendererDescription = rendererProvider.GetViewRenderer();

            if (pipelineType == PipelineType.Get) {
                return _pipelines.FirstOrDefault(p => p.Name == rendererDescription.GetPipeline);
            }
            else {
                return _pipelines.FirstOrDefault(p => p.Name == rendererDescription.PostPipeline);
            }
        }

        private void initializePipelines() {
            _pipelines = new List<PipelineDescriptor>();

            LibraryProvider libProvider = new LibraryProvider();
            foreach (Assembly assembly in libProvider.GetPipelineAssemblies()) {
                foreach (Type pipelineType in assembly.GetTypes().Where(t => typeof(IPipeline).IsAssignableFrom(t))) {

                    PipelineAttribute pipelineAttribute = pipelineType.GetCustomAttribute<PipelineAttribute>(true);
                    if (pipelineAttribute == null) continue;

                    PipelineDescriptor descriptor = new PipelineDescriptor() {
                        Name = pipelineAttribute.Name,
                        PipelineType = pipelineType
                    };
                    _pipelines.Add(descriptor);
                }
            }
        }
    }

    public enum PipelineType {
        Get,
        Post
    }
}
